package ee.ut.aa.neuraltic.logic;

import java.util.List;

import org.apache.log4j.Logger;

import ee.ut.aa.neuraltic.model.Board;
import ee.ut.aa.neuraltic.model.NeuralPlayer;
import ee.ut.aa.neuraltic.model.Player;
import ee.ut.aa.neuraltic.model.FirBoard;
import ee.ut.aa.neuraltic.neural.Network;

public class CompetitionThread extends Thread {

	private static Logger log = Logger.getLogger( CompetitionThread.class );

	private BoardEvaluator eval = FirEvaluator.getInstance();

	private Network one;
	private List<Network> pop;

	public CompetitionThread( Network one, List<Network> pop)
	{
		this.one = one;
		this.pop = pop;
	}

	public void run()
	{
		log.debug( "Starting competition in thread." );
		for( Network netTwo : pop ) {			

			NeuralPlayer plOne = new NeuralPlayer( Board.PLAYER_ONE, one );
			NeuralPlayer plTwo = new NeuralPlayer( Board.PLAYER_TWO, netTwo );

			Player winner = competition( plOne, plTwo, new FirBoard() );

			if( winner == plOne ) {
				one.setValue( one.getValue() + GeneticTrainer.WINVALUE );
				netTwo.setValue( netTwo.getValue() + GeneticTrainer.LOSSVALUE );
			} else if( winner == plTwo ) {
				one.setValue( one.getValue() + GeneticTrainer.LOSSVALUE2 );
				netTwo.setValue( netTwo.getValue() + GeneticTrainer.WINVALUE2 );
			} else {
				one.setValue( one.getValue() + GeneticTrainer.DRAWVALUE );
				netTwo.setValue( netTwo.getValue() + GeneticTrainer.DRAWVALUE2 );
			}				

		}
	}

	private Player competition( Player pOne, Player pTwo, Board board ) {

		log.debug( "Competition starting." );

		int i = 0;

		// Just to avoid infinite loop
		while( i++ < 1000 ) {

			if( !eval.isGameOver( board ) )
				pOne.makeNextMove( board );
			else
				break;

			log.debug( board );

			if( !eval.isGameOver( board ) )
				pTwo.makeNextMove( board );
			else
				break;

			log.debug( board );
		}

		int winner = eval.findWinner( board );

		log.debug( "Competition ended. Winner is player=" + winner );

		if( pOne.getValue() == winner )
			return pOne;
		if( pTwo.getValue() == winner )
			return pTwo;

		return null;
	}
}
